home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / tsipp / tsipp.lha / tsipp3.0a / src / tSippLight.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-02  |  17.5 KB  |  516 lines

  1. /*
  2.  *=============================================================================
  3.  *                                  tSippLight.c
  4.  *-----------------------------------------------------------------------------
  5.  * Tcl commands to manage SIPP light sources.
  6.  *-----------------------------------------------------------------------------
  7.  * Copyright 1992 Mark Diekhans
  8.  * Permission to use, copy, modify, and distribute this software and its
  9.  * documentation for any purpose and without fee is hereby granted, provided
  10.  * that the above copyright notice appear in all copies.  Mark Diekhans makes
  11.  * no representations about the suitability of this software for any purpose.
  12.  * It is provided "as is" without express or implied warranty.
  13.  *-----------------------------------------------------------------------------
  14.  * $Id: tSippLight.c,v 2.0 1992/11/02 03:56:21 markd Rel $
  15.  *=============================================================================
  16.  */
  17.  
  18. #include "tSippInt.h"
  19.  
  20. /*
  21.  * Constants indicating light types.
  22.  */
  23. #define TSIPP_LIGHTSOURCE  1
  24. #define TSIPP_SPOTLIGHT    2
  25.  
  26. /*
  27.  * Internal function prototypes.
  28.  */
  29. static void
  30. BindLightToHandle _ANSI_ARGS_((tSippGlob_pt  tSippGlobPtr,
  31.                                Lightsource  *lightPtr));
  32.  
  33. static Lightsource *
  34. LightHandleToPtr _ANSI_ARGS_((tSippGlob_pt    tSippGlobPtr,
  35.                               char           *handle,
  36.                               unsigned        validTypes));
  37.  
  38. /*=============================================================================
  39.  * BindLightToHandle --
  40.  *   Bind a lightsource to a handle, setting up the table entry.
  41.  *
  42.  * Parameters:
  43.  *   o tSippGlobPtr (I) - Pointer to the Tcl SIPP globals.  The handle is
  44.  *     returned in interp->result.
  45.  *   o lightPtr (I) - A pointer to the light source.
  46.  *-----------------------------------------------------------------------------
  47.  */
  48. static void
  49. BindLightToHandle (tSippGlobPtr, lightPtr)
  50.     tSippGlob_pt  tSippGlobPtr;
  51.     Lightsource  *lightPtr;
  52. {
  53.     Lightsource  **lightEntryPtr;
  54.  
  55.     lightEntryPtr = (Lightsource **)
  56.         Tcl_HandleAlloc (tSippGlobPtr->lightTblPtr,
  57.                          tSippGlobPtr->interp->result);
  58.     *lightEntryPtr = lightPtr;
  59. }
  60.  
  61. /*=============================================================================
  62.  * LightHandleToPtr --
  63.  *   Utility procedure to convert a light handle to a light pointer.
  64.  * Parameters:
  65.  *   o tSippGlobPtr (I) - A pointer to the Tcl SIPP global structure.
  66.  *   o handle (I) - A light handle.
  67.  *   o validTypes (I) - Indicates the type of light this operation is valid
  68.  *     for. These are bit flags, more than one may be or-ed together:
  69.  *        o TSIPP_LIGHTSOURCE - If the operation is valid for lightsources.
  70.  *        o TSIPP_SPOTLIGHT - If the lightsource is valid for spotlights.
  71.  * Returns:
  72.  *   A pointer to the lightsource or spot light, or NULL if an error occured.
  73.  *-----------------------------------------------------------------------------
  74.  */
  75. static Lightsource *
  76. LightHandleToPtr (tSippGlobPtr, handle, validTypes)
  77.     tSippGlob_pt    tSippGlobPtr;
  78.     char           *handle;
  79.     unsigned        validTypes;
  80. {
  81.     Lightsource **lightEntryPtr;
  82.  
  83.     lightEntryPtr = (Lightsource **)
  84.         Tcl_HandleXlate (tSippGlobPtr->interp, 
  85.                          tSippGlobPtr->lightTblPtr, handle);
  86.     if (lightEntryPtr == NULL)
  87.         return NULL;
  88.  
  89.     switch ((*lightEntryPtr)->type) {
  90.         case LIGHT_DIRECTION:
  91.         case LIGHT_POINT:
  92.             if (!(TSIPP_LIGHTSOURCE & validTypes)) {
  93.                  Tcl_AppendResult (tSippGlobPtr->interp,
  94.                                     "operation not valid on lightsources",
  95.                                     (char *) NULL);
  96.                  return NULL;
  97.             }
  98.             break;
  99.         case SPOT_SHARP:
  100.         case SPOT_SOFT:
  101.             if (!(TSIPP_SPOTLIGHT & validTypes)) {
  102.                  Tcl_AppendResult (tSippGlobPtr->interp,
  103.                                    "operation not valid on spotlights",
  104.                                    (char *) NULL);
  105.                  return NULL;
  106.             }
  107.             break;
  108.     };
  109.     return *lightEntryPtr;
  110.  
  111. } /* LightHandleToPtr */
  112.  
  113. /*=============================================================================
  114.  * SippLightSourceCreate --
  115.  *   Implements the command:
  116.  *     SippLightSourceCreate {x y z} color type
  117.  * Note:
  118.  *   This procedure has standard Tcl command calling sematics.  ClientData
  119.  * contains a pointer to the Tcl SIPP global structure.
  120.  *-----------------------------------------------------------------------------
  121.  */
  122. static int
  123. SippLightSourceCreate (clientData, interp, argc, argv)
  124.     char       *clientData;
  125.     Tcl_Interp *interp;
  126.     int         argc;
  127.     char      **argv;
  128. {
  129.     tSippGlob_pt    tSippGlobPtr = (tSippGlob_pt) clientData;
  130.     Vector          vector;
  131.     Color           intensity;
  132.     int             type;
  133.     Lightsource    *lightPtr;
  134.  
  135.     if (argc != 4) {
  136.         Tcl_AppendResult (interp, "wrong # args: ", argv [0],
  137.                           " {x y z} color type", (char *) NULL);
  138.         return TCL_ERROR;
  139.     }                     
  140.     if (!TSippConvertVertex (tSippGlobPtr, argv [1], &vector))
  141.         return TCL_ERROR;
  142.     if (!TSippConvertColor (tSippGlobPtr, argv [2], &intensity))
  143.         return TCL_ERROR;
  144.     if (STREQU (argv [3], "DIRECTION"))
  145.         type = LIGHT_DIRECTION;
  146.     else if (STREQU (argv [3], "POINT"))
  147.         type = LIGHT_POINT;
  148.     else {
  149.         Tcl_AppendResult (interp, "expected one of \"DIRECTION\" or ",
  150.                           "\"POINT\", got \"", argv [3], "\"", (char *) NULL);
  151.         return TCL_ERROR;
  152.     }
  153.     lightPtr = lightsource_create (vector.x, vector.y, vector.z,
  154.                                    intensity.red, intensity.grn, intensity.blu,
  155.                                    type);
  156.     BindLightToHandle (tSippGlobPtr, lightPtr);
  157.     return TCL_OK;
  158.  
  159. } /* SippLightSourceCreate */
  160.  
  161. /*=============================================================================
  162.  * SippSpotLightCreate --
  163.  *   Implements the command:
  164.  *     SippSpotLightCreate position point opening color type shadow
  165.  * Note:
  166.  *   This procedure has standard Tcl command calling sematics.  ClientData
  167.  * contains a pointer to the Tcl SIPP global structure.
  168.  *-----------------------------------------------------------------------------
  169.  */
  170. static int
  171. SippSpotLightCreate (clientData, interp, argc, argv)
  172.     char       *clientData;
  173.     Tcl_Interp *interp;
  174.     int         argc;
  175.     char      **argv;
  176. {
  177.     tSippGlob_pt    tSippGlobPtr = (tSippGlob_pt) clientData;
  178.     Vector          position, point;
  179.     double          opening;
  180.     Color           color;
  181.     int             type, shadow;
  182.     Lightsource    *lightPtr;
  183.  
  184.     if (argc != 7) {
  185.         Tcl_AppendResult (interp, "wrong # args: ", argv [0],
  186.                           " position point opening color type shadow",
  187.                           (char *) NULL);
  188.         return TCL_ERROR;
  189.     }                     
  190.     if (!TSippConvertVertex (tSippGlobPtr, argv [1], &position))
  191.         return TCL_ERROR;
  192.     if (!TSippConvertVertex (tSippGlobPtr, argv [2], &point))
  193.         return TCL_ERROR;
  194.     if (!TSippConvertAngleDeg (tSippGlobPtr, argv [3], &opening))
  195.         return TCL_ERROR;
  196.     if (!TSippConvertColor (tSippGlobPtr, argv [4], &color))
  197.         return TCL_ERROR;
  198.     if (STREQU (argv [5], "SHARP"))
  199.         type = SPOT_SHARP;
  200.     else if (STREQU (argv [5], "SOFT"))
  201.         type = SPOT_SOFT;
  202.     else {
  203.         Tcl_AppendResult (interp, "expected one of \"SHARP\" or ",
  204.                           "\"SOFT\", got \"", argv [5], "\"", (char *) NULL);
  205.         return TCL_ERROR;
  206.     }
  207.     if (Tcl_GetBoolean (interp, argv [6], &shadow) != TCL_OK)
  208.         return TCL_ERROR;
  209.  
  210.     lightPtr = spotlight_create (position.x, position.y, position.z,
  211.                                  point.x,    point.y,    point.z,
  212.                                  opening,
  213.                                  color.red,  color.grn,  color.blu,
  214.                                  type, shadow);
  215.  
  216.     BindLightToHandle (tSippGlobPtr, lightPtr);
  217.     return TCL_OK;
  218.  
  219. } /* SippSpotLightCreate */
  220.  
  221. /*=============================================================================
  222.  * SippLightDestruct --
  223.  *   Implements the command:
  224.  *     SippLightDestruct lightlist
  225.  * Note:
  226.  *   This procedure has standard Tcl command calling sematics.  ClientData
  227.  * contains a pointer to the Tcl SIPP global structure.
  228.  *-----------------------------------------------------------------------------
  229.  */
  230. static int
  231. SippLightDestruct (clientData, interp, argc, argv)
  232.     char       *clientData;
  233.     Tcl_Interp *interp;
  234.     int         argc;
  235.     char      **argv;
  236. {
  237.     tSippGlob_pt    tSippGlobPtr = (tSippGlob_pt) clientData;
  238.     handleList_t    lightList;
  239.     handleList_t    lightEntryList;
  240.     int             idx;
  241.  
  242.     if (argc != 2) {
  243.         Tcl_AppendResult (interp, "wrong # args: ", argv [0], " lightlist",
  244.                           (char *) NULL);
  245.         return TCL_ERROR;
  246.     }
  247.     if (!TSippHandleListConvert (tSippGlobPtr, tSippGlobPtr->lightTblPtr,
  248.                                  argv [1], &lightList, &lightEntryList))
  249.         return TCL_ERROR;
  250.  
  251.     for (idx = 0; idx < lightList.len; idx++) {
  252.         light_destruct ((Lightsource *) lightList.ptr [idx]);
  253.         Tcl_HandleFree (tSippGlobPtr->lightTblPtr, lightEntryList.ptr [idx]);
  254.     }
  255.  
  256.     TSippHandleListFree (&lightList);
  257.     TSippHandleListFree (&lightEntryList);
  258.     return TCL_OK;
  259.  
  260. } /* SippLightDestruct */
  261.  
  262. /*=============================================================================
  263.  * SippLightSourcePut --
  264.  *   Implements the command:
  265.  *     SippLightSourcePut light {x y z}
  266.  * Note:
  267.  *   This procedure has standard Tcl command calling sematics.  ClientData
  268.  * contains a pointer to the Tcl SIPP global structure.
  269.  *-----------------------------------------------------------------------------
  270.  */
  271. static int
  272. SippLightSourcePut (clientData, interp, argc, argv)
  273.     char       *clientData;
  274.     Tcl_Interp *interp;
  275.     int         argc;
  276.     char      **argv;
  277. {
  278.     tSippGlob_pt   tSippGlobPtr = (tSippGlob_pt) clientData;
  279.     Lightsource   *lightPtr;
  280.     Vector         point;
  281.  
  282.     if (argc != 3) {
  283.         Tcl_AppendResult (interp, "wrong # args: ", argv [0], 
  284.                           " light {x y z}", (char *) NULL);
  285.         return TCL_ERROR;
  286.     }
  287.     lightPtr = LightHandleToPtr (tSippGlobPtr, argv [1],
  288.                                  TSIPP_LIGHTSOURCE);
  289.     if (lightPtr == NULL)
  290.         return TCL_ERROR;
  291.     if (!TSippConvertVertex (tSippGlobPtr, argv [2], &point))
  292.         return TCL_ERROR;
  293.  
  294.     lightsource_put (lightPtr, point.x, point.y, point.z);
  295.     return TCL_OK;
  296.  
  297. } /* SippLightSourcePut */
  298.  
  299. /*=============================================================================
  300.  * SippSpotLightPos --
  301.  *   Implements the command:
  302.  *     SippSpotLightPos light {x y z}
  303.  * Note:
  304.  *   This procedure has standard Tcl command calling sematics.  ClientData
  305.  * contains a pointer to the Tcl SIPP global structure.
  306.  *-----------------------------------------------------------------------------
  307.  */
  308. static int
  309. SippSpotLightPos (clientData, interp, argc, argv)
  310.     char       *clientData;
  311.     Tcl_Interp *interp;
  312.     int         argc;
  313.     char      **argv;
  314. {
  315.     tSippGlob_pt   tSippGlobPtr = (tSippGlob_pt) clientData;
  316.     Lightsource   *lightPtr;
  317.     Vector         point;
  318.  
  319.     if (argc != 3) {
  320.         Tcl_AppendResult (interp, "wrong # args: ", argv [0], 
  321.                           " light {x y z}", (char *) NULL);
  322.         return TCL_ERROR;
  323.     }
  324.     lightPtr = LightHandleToPtr (tSippGlobPtr, argv [1],
  325.                                  TSIPP_SPOTLIGHT);
  326.     if (lightPtr == NULL)
  327.         return TCL_ERROR;
  328.     if (!TSippConvertVertex (tSippGlobPtr, argv [2], &point))
  329.         return TCL_ERROR;
  330.  
  331.     spotlight_pos (lightPtr, point.x, point.y, point.z);
  332.     return TCL_OK;
  333.  
  334. } /* SippSpotLightPos */
  335.  
  336. /*=============================================================================
  337.  * SippSpotLightOpening --
  338.  *   Implements the command:
  339.  *     SippSpotLightOpening light opening
  340.  * Note:
  341.  *   This procedure has standard Tcl command calling sematics.  ClientData
  342.  * contains a pointer to the Tcl SIPP global structure.
  343.  *-----------------------------------------------------------------------------
  344.  */
  345. static int
  346. SippSpotLightOpening (clientData, interp, argc, argv)
  347.     char       *clientData;
  348.     Tcl_Interp *interp;
  349.     int         argc;
  350.     char      **argv;
  351. {
  352.     tSippGlob_pt   tSippGlobPtr = (tSippGlob_pt) clientData;
  353.     Lightsource   *lightPtr;
  354.     double         opening;
  355.  
  356.     if (argc != 3) {
  357.         Tcl_AppendResult (interp, "wrong # args: ", argv [0], 
  358.                           " light opening", (char *) NULL);
  359.         return TCL_ERROR;
  360.     }
  361.     lightPtr = LightHandleToPtr (tSippGlobPtr, argv [1],
  362.                                  TSIPP_SPOTLIGHT);
  363.     if (lightPtr == NULL)
  364.         return TCL_ERROR;
  365.     if (!TSippConvertAngleDeg (tSippGlobPtr, argv [2], &opening))
  366.         return TCL_ERROR;
  367.  
  368.     spotlight_opening (lightPtr, opening);
  369.     return TCL_OK;
  370.  
  371. } /* SippSpotLightOpening */
  372.  
  373. /*=============================================================================
  374.  * SippSpotLightShadows --
  375.  *   Implements the command:
  376.  *     SippSpotLightShadows light flag
  377.  * Note:
  378.  *   This procedure has standard Tcl command calling sematics.  ClientData
  379.  * contains a pointer to the Tcl SIPP global structure.
  380.  *-----------------------------------------------------------------------------
  381.  */
  382. static int
  383. SippSpotLightShadows (clientData, interp, argc, argv)
  384.     char       *clientData;
  385.     Tcl_Interp *interp;
  386.     int         argc;
  387.     char      **argv;
  388. {
  389.     tSippGlob_pt   tSippGlobPtr = (tSippGlob_pt) clientData;
  390.     Lightsource   *lightPtr;
  391.     int            flag;
  392.  
  393.     if (argc != 3) {
  394.         Tcl_AppendResult (interp, "wrong # args: ", argv [0], 
  395.                           " light flag", (char *) NULL);
  396.         return TCL_ERROR;
  397.     }
  398.     lightPtr = LightHandleToPtr (tSippGlobPtr, argv [1],
  399.                                  TSIPP_SPOTLIGHT);
  400.     if (lightPtr == NULL)
  401.         return TCL_ERROR;
  402.     if (Tcl_GetBoolean (interp, argv [2], &flag) != TCL_OK)
  403.         return TCL_ERROR;
  404.  
  405.     spotlight_shadows (lightPtr, flag);
  406.     return TCL_OK;
  407.  
  408. } /* SippSpotLightShadows */
  409.  
  410. /*=============================================================================
  411.  * SippLightColor --
  412.  *   Implements the command:
  413.  *     SippLightColor light color
  414.  * Note:
  415.  *   This procedure has standard Tcl command calling sematics.  ClientData
  416.  * contains a pointer to the Tcl SIPP global structure.
  417.  *-----------------------------------------------------------------------------
  418.  */
  419. static int
  420. SippLightColor (clientData, interp, argc, argv)
  421.     char       *clientData;
  422.     Tcl_Interp *interp;
  423.     int         argc;
  424.     char      **argv;
  425. {
  426.     tSippGlob_pt   tSippGlobPtr = (tSippGlob_pt) clientData;
  427.     Lightsource   *lightPtr;
  428.     Color          color;
  429.  
  430.     if (argc != 3) {
  431.         Tcl_AppendResult (interp, "wrong # args: ", argv [0], 
  432.                           " light color", (char *) NULL);
  433.         return TCL_ERROR;
  434.     }
  435.     lightPtr = LightHandleToPtr (tSippGlobPtr, argv [1],
  436.                                  TSIPP_LIGHTSOURCE | TSIPP_SPOTLIGHT);
  437.     if (lightPtr == NULL)
  438.         return TCL_ERROR;
  439.     if (!TSippConvertColor (tSippGlobPtr, argv [2], &color))
  440.         return TCL_ERROR;
  441.  
  442.     light_color (lightPtr, color.red, color.blu, color.grn);
  443.     return TCL_OK;
  444.  
  445. } /* SippLightColor */
  446.  
  447. /*=============================================================================
  448.  * SippLightActive --
  449.  *   Implements the command:
  450.  *     SippLightActive light flag
  451.  * Note:
  452.  *   This procedure has standard Tcl command calling sematics.  ClientData
  453.  * contains a pointer to the Tcl SIPP global structure.
  454.  *-----------------------------------------------------------------------------
  455.  */
  456. static int
  457. SippLightActive (clientData, interp, argc, argv)
  458.     char       *clientData;
  459.     Tcl_Interp *interp;
  460.     int         argc;
  461.     char      **argv;
  462. {
  463.     tSippGlob_pt   tSippGlobPtr = (tSippGlob_pt) clientData;
  464.     Lightsource   *lightPtr;
  465.     int            flag;
  466.  
  467.     if (argc != 3) {
  468.         Tcl_AppendResult (interp, "wrong # args: ", argv [0], 
  469.                           " light flag", (char *) NULL);
  470.         return TCL_ERROR;
  471.     }
  472.     lightPtr = LightHandleToPtr (tSippGlobPtr, argv [1],
  473.                                  TSIPP_LIGHTSOURCE | TSIPP_SPOTLIGHT);
  474.     if (lightPtr == NULL)
  475.         return TCL_ERROR;
  476.     if (Tcl_GetBoolean (interp, argv [2], &flag) != TCL_OK)
  477.         return TCL_ERROR;
  478.  
  479.     light_active (lightPtr, flag);
  480.     return TCL_OK;
  481.  
  482. } /* SippLightActive */
  483.  
  484. /*=============================================================================
  485.  * TSippLightInit --
  486.  *   Initialized the light source commands.
  487.  *
  488.  * Parameters:
  489.  *   o tclSippGlobP (I) - Pointer to the top level global data structure.
  490.  *     (currently unused).
  491.  *-----------------------------------------------------------------------------
  492.  */
  493. void
  494. TSippLightInit (tSippGlobPtr)
  495.     tSippGlob_pt    tSippGlobPtr;
  496. {
  497.     static tSippTclCmdTbl_t cmdTable [] = {
  498.         {"SippLightSourceCreate",  SippLightSourceCreate},
  499.         {"SippSpotLightCreate",    SippSpotLightCreate},
  500.         {"SippLightDestruct",      SippLightDestruct},
  501.         {"SippLightSourcePut",     SippLightSourcePut},
  502.         {"SippSpotLightPos",       SippSpotLightPos},
  503.         {"SippSpotLightOpening",   SippSpotLightOpening},
  504.         {"SippSpotLightShadows",   SippSpotLightShadows},
  505.         {"SippLightColor",         SippLightColor},
  506.         {"SippLightActive",        SippLightActive},
  507.         {NULL,                     NULL}
  508.     };
  509.  
  510.     tSippGlobPtr->lightTblPtr = 
  511.        Tcl_HandleTblInit ("light", sizeof (Lightsource *), 4);
  512.  
  513.     TSippInitCmds (tSippGlobPtr, cmdTable);
  514.  
  515. } /* TSippLightInit */
  516.